package com.edu.whty.common.tools;

import com.alibaba.fastjson.JSONObject;
import com.edu.whty.common.constants.Constant;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;

/**
 * @author xmb
 * @ClassName: HttpClientUtil
 * @Description: http请求封装
 * @date 2013-12-26 下午02:48:01
 */
public class HttpClientUtil {
    private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

    public static final String post(final String url, Map<String, String> params, String netIp) {
        long start = System.currentTimeMillis();
        if (!StringUtil.isNotNull(url)) {
            return null;
        }
        HttpClient client = new DefaultHttpClient();
        String content = null;
        String exceptionMes = "";
        try {
            try {
                HttpPost post = new HttpPost(url);
                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(params == null ? 0 : params.size());
                if (params != null && params.size() > 0) {
                    String key = null;
                    for (Iterator iter = params.keySet().iterator(); iter.hasNext(); ) {
                        key = (String) iter.next();
                        nameValuePairs.add(new BasicNameValuePair(key, params.get(key)));
                    }
                    post.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8));
                }
                if (null != netIp && IpUtils.isRightIP(netIp)) {
                    post.setHeader("x-forwarded-for", netIp);
                }
                HttpResponse response = client.execute(post);
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    content = EntityUtils.toString(entity);
                }
                EntityUtils.consume(entity);
            } catch (UnsupportedEncodingException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (ParseException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (IOException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            }
        } finally {
            client.getConnectionManager().shutdown();
        }
        long end = new Date().getTime();
        //外部接口日志
        String costTime = end - start + "";
        String body = "{}";
        if (null != params && params.size() > 0) {
            body = JSONObject.toJSONString(params);
        }
        //请求返回
        String returnStr = null;
        if (null != content && content.trim().length() > 500) {
            returnStr = content.substring(0, 500);
        } else {
            returnStr = content;
        }
        if (null != exceptionMes && exceptionMes.trim().length() > 500) {
            exceptionMes = exceptionMes.substring(0, 500);
        }
        printElkLog(url, body, costTime, exceptionMes, returnStr, netIp, "未获取", null);
        return content;
    }

    private static void printElkLog(String url, String body, String costTime, String exceptionMes, String returnStr,
                                    String netIp, String responseStatus, Map<String, String> headers) {
        if (null != body) {
            body = body.replace("\"", "\\\"");
        }
        if (null != returnStr) {
            returnStr = returnStr.replace("\"", "\\\"");
        }
        MDC.put("url", url);
        MDC.put("body", body);
        MDC.put("costTime", costTime);
        MDC.put("exceptionMes", exceptionMes);
        MDC.put("responseStatus", responseStatus);
        MDC.put("description", returnStr);
        MDC.put("requestIp", netIp);
        if (null != headers && headers.size() > 0) {
            MDC.put("requestHeader", ((JSONObject) JSONObject.toJSON(headers)).toJSONString().replace("\"", "\\\""));
        }
        logger.error("外部接口请求信息");
    }

    public static final String post(final String url, Map<String, String> params, Map<String, String> headers, String netIp) {
        long start = System.currentTimeMillis();
        if (!StringUtil.isNotNull(url)) {
            return null;
        }
        HttpClient client = new DefaultHttpClient();
        String content = null;
        String exceptionMes = null;
        try {
            try {
                HttpPost post = new HttpPost(url);
                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(params == null ? 0 : params.size());
                if (headers != null && headers.size() > 0) {
                    String key = null;
                    for (Iterator iter = headers.keySet().iterator(); iter.hasNext(); ) {
                        key = (String) iter.next();
                        post.setHeader(key, headers.get(key));
                    }
                }
                if (params != null && params.size() > 0) {
                    String key = null;
                    for (Iterator iter = params.keySet().iterator(); iter.hasNext(); ) {
                        key = (String) iter.next();
                        nameValuePairs.add(new BasicNameValuePair(key, params.get(key)));
                    }
                    post.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8));
                }
                if (null != netIp && IpUtils.isRightIP(netIp)) {
                    post.setHeader("x-forwarded-for", netIp);
                }
                HttpResponse response = client.execute(post);
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    content = EntityUtils.toString(entity);
                }
                EntityUtils.consume(entity);
            } catch (UnsupportedEncodingException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (ParseException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (IOException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            }
        } finally {
            client.getConnectionManager().shutdown();
        }
        long end = new Date().getTime();
        //外部接口日志
        String costTime = end - start + "";
        String body = "{}";
        if (null != params && params.size() > 0) {
            body = JSONObject.toJSONString(params);
        }
        //请求返回
        String returnStr = null;
        if (null != content && content.trim().length() > 500) {
            returnStr = content.substring(0, 500);
        } else {
            returnStr = content;
        }
        if (null != exceptionMes && exceptionMes.trim().length() > 500) {
            exceptionMes = exceptionMes.substring(0, 500);
        }
        printElkLog(url, body, costTime, exceptionMes, returnStr, netIp, "未获取", headers);
        return content;
    }

    public static final String post(final String url, String reqBody, Map<String, String> headers, String netIp) {

        long start = new Date().getTime();

        if (!StringUtil.isNotNull(url)) {
            return null;
        }
        logger.info("请求报文:\n" + reqBody);
        HttpClient client = new DefaultHttpClient();
        String content = null;
        String exceptionMes = null;
        try {
            try {
                HttpPost post = new HttpPost(url);
                if (headers != null && headers.size() > 0) {
                    String key = null;
                    for (Iterator iter = headers.keySet().iterator(); iter.hasNext(); ) {
                        key = (String) iter.next();
                        post.setHeader(key, headers.get(key));
                    }
                }
                post.setEntity(new StringEntity(reqBody, HTTP.UTF_8));
                post.setHeader("Content-Type", "application/json;charset=UTF-8");
                if (null != netIp && IpUtils.isRightIP(netIp)) {
                    post.setHeader("x-forwarded-for", netIp);
                }
                HttpResponse response = client.execute(post);
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    content = IOUtils.toString(entity.getContent(),
                            "UTF-8");
                }
                EntityUtils.consume(entity);
            } catch (UnsupportedCharsetException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (UnsupportedOperationException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (IOException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            }
        } finally {
            client.getConnectionManager().shutdown();
        }
        long end = new Date().getTime();
        //外部接口日志
        String costTime = end - start + "";
        String body = "{}";
        if (null != reqBody) {
            body = reqBody;
        }
        //请求返回
        String returnStr = null;
        if (null != content && content.trim().length() > 500) {
            returnStr = content.substring(0, 500);
        } else {
            returnStr = content;
        }
        if (null != exceptionMes && exceptionMes.trim().length() > 500) {
            exceptionMes = exceptionMes.substring(0, 500);
        }
        printElkLog(url, body, costTime, exceptionMes, returnStr, netIp, "未获取", headers);
        return content;
    }

    public static final String post(final String url, String reqBody, String netIp) {
        long start = new Date().getTime();
        if (!StringUtil.isNotNull(url)) {
            return null;
        }
        if (url.startsWith("https:")) {
            //采用https接口工具类请求
            return HttpsUtil.doPost(url, reqBody, netIp);
        }
        logger.info("请求报文:\n" + reqBody);
        HttpClient client = new DefaultHttpClient();
        String content = null;
        String exceptionMes = null;
        try {
            try {
                HttpPost post = new HttpPost(url);
                post.setEntity(new StringEntity(reqBody, HTTP.UTF_8));
                post.setHeader("Content-Type", "text/html;charset=UTF-8");
                HttpResponse response = client.execute(post);
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    content = IOUtils.toString(entity.getContent(),
                            "UTF-8");
                }
                if (null != netIp && IpUtils.isRightIP(netIp)) {
                    post.setHeader("x-forwarded-for", netIp);
                }
                EntityUtils.consume(entity);
            } catch (UnsupportedCharsetException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (UnsupportedOperationException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (IOException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            }
        } finally {
            client.getConnectionManager().shutdown();
        }
        long end = new Date().getTime();
        //外部接口日志
        String costTime = end - start + "";
        String body = "{}";
        if (null != reqBody) {
            body = reqBody;
        }
        //请求返回
        String returnStr = null;
        if (null != content && content.trim().length() > 500) {
            returnStr = content.substring(0, 500);
        } else {
            returnStr = content;
        }
        if (null != exceptionMes && exceptionMes.trim().length() > 500) {
            exceptionMes = exceptionMes.substring(0, 500);
        }
        printElkLog(url, body, costTime, exceptionMes, returnStr, netIp, "未获取", null);
        return content;
    }

    public static final String post(final String url, String reqBody, int timeout, String netIp) {
        long start = new Date().getTime();
        if (!StringUtil.isNotNull(url)) {
            return null;
        }
        logger.info("请求报文:\n" + reqBody);
        HttpClient client = new DefaultHttpClient();
        client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout);
        String content = null;
        String exceptionMes = null;
        try {
            try {
                HttpPost post = new HttpPost(url);
                post.setEntity(new StringEntity(reqBody, HTTP.UTF_8));
                post.setHeader("Content-Type", "text/html;charset=UTF-8");
                HttpResponse response = client.execute(post);
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    content = IOUtils.toString(entity.getContent(),
                            "UTF-8");
                }
                if (null != netIp && IpUtils.isRightIP(netIp)) {
                    post.setHeader("x-forwarded-for", netIp);
                }
                EntityUtils.consume(entity);
            } catch (UnsupportedCharsetException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (UnsupportedOperationException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            } catch (IOException e) {
                exceptionMes = e.getMessage();
                e.printStackTrace();
            }
        } finally {
            client.getConnectionManager().shutdown();
        }
        long end = new Date().getTime();
        //外部接口日志
        String costTime = end - start + "";
        String body = "{}";
        if (null != reqBody) {
            body = reqBody;
        }
        //请求返回
        String returnStr = null;
        if (null != content && content.trim().length() > 500) {
            returnStr = content.substring(0, 500);
        } else {
            returnStr = content;
        }
        if (null != exceptionMes && exceptionMes.trim().length() > 500) {
            exceptionMes = exceptionMes.substring(0, 500);
        }
        printElkLog(url, body, costTime, exceptionMes, returnStr, netIp, "未获取", null);
        return content;
    }

    public static final String get(final String url, String netIp) {
        long start = System.currentTimeMillis();
        if (!StringUtil.isNotNull(url)) {
            return null;
        }
        String exceptionMes = null;
        if (url.startsWith("https:")) {
            //采用https接口工具类请求
            return HttpsUtil.doGet(url, netIp);
        }
        org.apache.commons.httpclient.HttpClient client = new org.apache.commons.httpclient.HttpClient();
        //新增超时设置
        client.getHttpConnectionManager().getParams().setConnectionTimeout(3000);
        client.getHttpConnectionManager().getParams().setSoTimeout(3000);

        StringBuilder sb = new StringBuilder();
        InputStream ins = null;
        GetMethod method = new GetMethod(url);
        method.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
        method.setRequestHeader("Accept", "text/plain;charset=utf-8");

        method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                new DefaultHttpMethodRetryHandler(3, false));
        // Execute the method.  
        if (null != netIp && IpUtils.isRightIP(netIp)) {
            method.setRequestHeader("x-forwarded-for", netIp);
        }
        int statusCode = 0;
        try {
            statusCode = client.executeMethod(method);
            if (statusCode == HttpStatus.SC_OK) {
                ins = method.getResponseBodyAsStream();
                byte[] b = new byte[1024];
                int r_len = 0;
                while ((r_len = ins.read(b)) > 0) {
//			        sb.append(new String(b, 0, r_len, method  
//			                .getResponseCharSet()));
                    sb.append(new String(b, 0, r_len, "utf-8"));
                }
            } else {
                System.err.println("Response Code: " + statusCode);
            }
        } catch (HttpException e) {
            exceptionMes = e.getMessage();
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            exceptionMes = e.getMessage();
            e.printStackTrace();
        } catch (IOException e) {
            exceptionMes = e.getMessage();
            e.printStackTrace();
        }
        long end = new Date().getTime();
        //外部接口日志
        String costTime = end - start + "";
        String body = "{}";
        String content = sb.toString();
        //请求返回
        String returnStr = null;
        if (null != content && content.trim().length() > 500) {
            returnStr = content.substring(0, 500);
        } else {
            returnStr = content;
        }
        if (null != exceptionMes && exceptionMes.trim().length() > 500) {
            exceptionMes = exceptionMes.substring(0, 500);
        }
        printElkLog(url, body, costTime, exceptionMes, returnStr, netIp, statusCode + "", null);
        return sb.toString();
    }

    /**
     * 调用上传附件接口
     *
     * @param url       接口地址
     * @param file      上传附件
     * @param filedName 附件对应接口名
     * @param paraMap   基础参数
     * @return
     * @throws Exception
     */
    public static final String post(final String url, File file, String filedName, Map<String, String> paraMap, String netIp) throws Exception {
        if (!StringUtil.isNotNull(url) || file == null || !StringUtil.isNotNull(filedName)) {
            return null;
        }
        long start = new Date().getTime();
        logger.info("请求报文文件:\n" + file.getAbsolutePath());
        HttpClient client = new DefaultHttpClient();
        String content = null;
        try {
            HttpPost post = new HttpPost(url);
            MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE,
                    null, Charset.forName("UTF-8"));
            if (paraMap != null) {
                for (Map.Entry<String, String> entry : paraMap.entrySet()) {
                    reqEntity.addPart(entry.getKey(), new StringBody(entry.getValue(), Charset.forName("UTF-8")));
                }
            }
            reqEntity.addPart(filedName, new FileBody(file));//fileData为请求后台的File upload;属性
            post.setEntity(reqEntity);
            post.setHeader("content-disposition", "attachment;filename=" + file.getName());
            if (null != netIp && IpUtils.isRightIP(netIp)) {
                post.setHeader("x-forwarded-for", netIp);
            }
            HttpResponse response = client.execute(post);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                content = IOUtils.toString(entity.getContent(),
                        "UTF-8");
            }
            EntityUtils.consume(entity);
        } finally {
            client.getConnectionManager().shutdown();
        }
        long end = new Date().getTime();
        if (end - start > Constant.TIME) {
            logger.error("cms long time  error:  接口请求url=" + url + "&param=" + JSONObject.toJSONString(paraMap) + "&time=" + (end - start));
        } else {
            logger.info("cms time : 接口请求url=" + url + "&time=" + (end - start));
        }
        return content;
    }

    @SuppressWarnings("deprecation")
    public static CloseableHttpClient createSSLClientDefault() {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(
                    null, new TrustStrategy() {
                        // 信任所有
                        @Override
                        public boolean isTrusted(X509Certificate[] chain,
                                                 String authType) throws CertificateException {
                            return true;
                        }
                    }).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslContext);
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();
    }

    public static final String post1(final String url, String reqBody, String netIp) {
        long start = System.currentTimeMillis();
        if (!StringUtil.isNotNull(url)) {
            return null;
        }
        if (url.startsWith("https:")) {
            //采用https接口工具类请求
            return HttpsUtil.doPost1(url, reqBody, netIp);
        }
        logger.info("请求报文:\n" + url);
        logger.info("请求报文:\n" + reqBody);
        HttpClient client = new DefaultHttpClient();
        String content = null;
        String exceptionMes = null;
        try {
            HttpPost post = new HttpPost(url);
            post.setEntity(new StringEntity(reqBody, HTTP.UTF_8));
            post.setHeader("Content-Type", "application/json;charset=UTF-8");
            if (null != netIp && IpUtils.isRightIP(netIp)) {
                post.setHeader("x-forwarded-for", netIp);
            }
            HttpResponse response = client.execute(post);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                content = IOUtils.toString(entity.getContent(),
                        "UTF-8");
            }
            EntityUtils.consume(entity);
        } catch (Exception e) {
            logger.error("接cms 接口返回失败!\nURL:" + url + "\nparam:" + reqBody.toString());
            exceptionMes = e.getMessage();
        } finally {
            client.getConnectionManager().shutdown();
        }
        long end = System.currentTimeMillis();
        //外部接口日志
        String costTime = end - start + "";
        String body = "{}";
        if (null != reqBody) {
            body = reqBody;
        }
        //请求返回
        String returnStr = null;
        if (null != content && content.trim().length() > 500) {
            returnStr = content.substring(0, 500);
        } else {
            returnStr = content;
        }
        if (null != exceptionMes && exceptionMes.trim().length() > 500) {
            exceptionMes = exceptionMes.substring(0, 500);
        }
        printElkLog(url, body, costTime, exceptionMes, returnStr, netIp, "未获取", null);
        return content;
    }


    public static void main(String[] args) {
        String httpUrl = "http://demo726.ppmeet.cn/?r=/api/register";
        Map<String, String> para = new HashMap<String, String>();
        para.put("dpid", "");
        para.put("n", "q1");
        para.put("p", "123456");
        para.put("u", "mingchen1");
        para.put("code", "VD5WaANzCXAKYlI_W2VbOQVnVGQGblJpDyIBeA0oUTYFfwMiBzldY1Y3ADhUNVFkBTZWMlJqBWYJZA");
        para.put("key", "74be16979710d4c4e7c6647856088456");
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Referer", "http://localhost");
        try {
            logger.debug(post(httpUrl, para, headers, null));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            File fileupload = new File("C:\\Users\\zhujg\\Documents\\360截图\\360截图20171209180342466.jpg");
            String responseStr = HttpClientUtil.post("http://res.t.huijiaoyun.com:30022/cms-ft/uploadify", fileupload, "fileData", null, null);
            System.out.println("responseStr=" + responseStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
